using System;
using System.Collections;
using System.Runtime.InteropServices; 
using Ion.MarketView.Ifc;

namespace Tutorial_app
{
    public class SheetLauncher
    {
        private static String _reqServiceName;

        private static  String LOGIN_USER = "admin";
        private static  String LOGIN_PWD = "admin";

        private ObserverLogin _myObserverLogin = new ObserverLogin();
        private ObserverTrade _myObserverTrade = new ObserverTrade();
        private ObserverInstrument _myObserverInstrument = new ObserverInstrument();
        private ObserverOrder _myObserverOrder = new ObserverOrder();

        private static String _instrumentName = "";
        private LoginRec _loginRec = null;

        public static void Main(string[] args)
        {
            Application app = Application.Instance;
            SheetLauncher oTutorial = new SheetLauncher();
            
            app.Registered += oTutorial.HandleRegistered;
            app.NewService += oTutorial.HandleNewService;
            app.ServiceStatusUpdated += oTutorial.HandleUpdatedService;
            app.Started += HandleStarted;
            app.Stopped += HandleStopped;
             
            app.Initialize(args);
        }

        private static void HandleStopped(object sender, EventArgs args)
        {
            Console.Out.WriteLine("*** HandleStopped *** {0} ", args.ToString());
        }

        private static void HandleStarted(object sender, EventArgs args)
        {
            _reqServiceName = Application.Instance.MkvReadString("SERVICENAME", 0, "MOCK");
            Console.Out.WriteLine("Started reqServiceName = {0} ", _reqServiceName);
            
            // Extend the set of subscribed fields
            TradeRec.UseField(TradeRec.TradeBase.CouponInterest);
            TradeRec.UseField(TradeRec.TradeBase.ClearingHouse);

            OrderRec.UseField(OrderRec.OrderBase.CustomerInfo);
            OrderRec.UseField(OrderRec.OrderBase.FreeText);
            OrderRec.UseField(OrderRec.OrderBase.UserData);

            OrderRec.AddCustomField("OrderTmpId", Field.Type.String, "OrderTmpId");
        }

        private void HandleRegistered(object sender, RegistrationResultEventArgs args)
        {

        }

        private void HandleNewService(object sender, ServiceEventArgs args)
        {
            Console.Out.WriteLine("Service {0} available", args.Service.ComponentName);
        }

        private void HandleUpdatedService(object sender, ServiceEventArgs args)
        {
            Service service = args.Service;

            if (service.IsReady)
            {
                Console.Out.WriteLine("Service {0} is now Ready", args.Service.ComponentName);

                if (_reqServiceName == service.ComponentName)
                {
                    _myObserverInstrument.Supply += HandleSuppliedInstruments;
                    service.SubscribeInstruments(_myObserverInstrument);
                    Console.Out.WriteLine("Subscribed Instruments");

                    _myObserverTrade.Supply += HandleSuppliedTrades;
                    service.SubscribeTrades(_myObserverTrade);
                    Console.Out.WriteLine("Subscribed Trades");

                    _myObserverLogin.Supply += HandleSuppliedLogins;
                    service.SubscribeLogins(_myObserverLogin);
                    Console.Out.WriteLine("Subscribed Logins");

                    _myObserverOrder.CreateOwnOrder += HandleOwnOrders;
                    service.SubscribeOrders(_myObserverOrder);
                    Console.Out.WriteLine("Subscribed Orders");
                }
            }
            else if (!service.IsActive)
            {
                 Console.Out.WriteLine("Service {0} is NOT ready", args.Service.ComponentName);
            }
        }

        private void HandleResultLogin(object sender, RequestResultEventArgs args)
        {
            if (args.ErrorCode < 0)
            {
                Console.Out.WriteLine("Login Error ( {0} {1} )", args.ErrorCode, args.ErrorMessage);
            }
            else
            {
                Console.Out.WriteLine("Login ( {0} {1} )", args.ErrorCode, args.ErrorMessage);
            }
        }

        private void HandleSuppliedLogins(object sender, LoginRecEventArgs args)
        {
            LoginRec loginRec = args.Record;

            if (loginRec.User != LOGIN_USER)
            {
               return;
            }

            Console.Out.WriteLine("Supplied Login {0}", loginRec.User);

            if (!loginRec.IsTraderOn)
            {
                loginRec.TraderOn(_myObserverLogin);
                Console.Out.WriteLine("Sending TraderOn for user {0}", LOGIN_USER);
            }

            else
            {
                Console.Out.WriteLine("TraderOn set for user {0}", LOGIN_USER);

                _loginRec = loginRec;
                InstrumentRec instRec = (InstrumentRec)InstrumentRec.GetRecord(loginRec.Service, _instrumentName);
                OrderEntry orderEntry = OrderEntry.Create(loginRec, instRec, Verb.Buy, 101.5, 
                                                          10.0, 10.0, OrderType.Limit, OrderTimeInForce.FAS);

                Console.Out.WriteLine("Order Created with Id {0}", orderEntry.Id);

                orderEntry.SetParameter("FreeText", "my free text");
                orderEntry.CustomerInfo = "Tutorial";
                orderEntry.LocalData = "MyUserData";
                              
                _myObserverOrder.RequestResult += HandleOrderResult;
                orderEntry.Send(_myObserverOrder);
               
                Console.Out.WriteLine("Order sent on instrument ( {0} )", instRec.Id);
            }
        }

        private void HandleSuppliedTrades(object sender, TradeRecEventArgs args)
        {
            TradeRec tradeRec = (TradeRec) args.Record;
            if (args.IsNew)
            {
                Console.Out.WriteLine("Trade creation {0}", tradeRec.CompleteName);
            }
            else
            {
                Console.Out.WriteLine("Trade update {0}", tradeRec.CompleteName);
            }

            PrintTrade(tradeRec);
        }

        private void PrintTrade (TradeRec trade)
        {
            Console.Out.WriteLine(" [Trade] Id ( {0} )", trade.Id);
            Console.Out.WriteLine(" Price ( {0} )", trade.Value);
            Console.Out.WriteLine(" QtyNominal ( {0} )", trade.QtyNominal);
            Console.Out.WriteLine(" Verb ( {0} )", trade.Verb);

            
            if (trade.IsClearingHouseValid)
            {
                Console.Out.WriteLine("ClearingHouse ( {0} )", trade.ClearingHouse);
            }

            if (trade.IsCouponInterestValid)
            {
                Console.Out.WriteLine("CouponInterest ( {0} )", trade.CouponInterest);
            }

            // Instrument fields
            InstrumentRec instRec = trade.Instrument;
            if (instRec != null)
            {
                Console.Out.WriteLine(" [Instrument] Code {0}", instRec.Code);
                Console.Out.WriteLine(" [Instrument] Desc {0}", instRec.Desc);
            }
        }

        private void PrintOrder(OrderRec order)
        {
            Console.Out.WriteLine(" [Order] Id ( {0} )", order.Id);
            Console.Out.WriteLine(" Instrument ( {0} )", order.InstrumentId);
            Console.Out.WriteLine(" Price ( {0} )", order.Value);
            Console.Out.WriteLine(" QtyTot ( {0} )", order.QtyTot);
            Console.Out.WriteLine(" Verb ( {0} )", order.Verb);
            Console.Out.WriteLine(" Status ( {0} )", order.TradingStatus);
        }

        private void HandleSuppliedInstruments(object sender, InstrumentRecEventArgs args)
        {
            InstrumentRec instRec = args.Record;

            if (_instrumentName.Equals(""))
            {
                _instrumentName = instRec.Id;

                LoginEntry loginEntry = LoginEntry.Create(args.Record.Service, LOGIN_USER, LOGIN_PWD);
                _myObserverLogin.RequestResult += HandleResultLogin;
                loginEntry.Send(_myObserverLogin);
            }
        }

        private void HandleOwnOrders(object sender, OrderMatchingEventArgs args)
        {
            OrderRec orderRec = args.Record;
            
            PrintOrder(orderRec);

            Console.Out.WriteLine("Seding order rewrite for {0}", orderRec.Id);

            OrderRewriteEntry orderRewrite = OrderRewriteEntry.Create(_loginRec, orderRec, 25, 100, 100);

            ObserverOrder orderRewriteObserver = new ObserverOrder();
            orderRewriteObserver.RequestResult += HandleOrderRewriteResult;

            orderRewrite.Send(orderRewriteObserver);
        }

        private void HandleOrderResult(object sender, RequestResultEventArgs args)
        {
            if (args.ErrorCode > 0)
            {
                Console.Out.WriteLine("Order result ( {0} {1} )", args.ErrorCode, args.ErrorMessage);
            }
        }

        private void HandleOrderRewriteResult(object sender, RequestResultEventArgs args)
        {
               Console.Out.WriteLine("Order result ( {0} {1} )", args.ErrorCode, args.ErrorMessage);
        }

        
    }
}

